// #include<iostream>

// int main()
// {
//     std::cout<<"server makefile test!!!"<<std::endl;
//     return 0;
// }

#include "http_server.hpp"
#include <memory>
#include "protocol.hpp"
#include <fstream>

#define index

void user()
{
    std::cout << "use error !!!!! \n\n    user->  server [port_number] \n\n"
              << std::endl;
}

bool readfile(std::string path, std::string suffix, std::string &body)
{
    // c++读取文件的时候 fstream 还是挺好的
    std::ifstream fin;
    if (suffix == ".html")
    {
        fin.open(path);
    }
    else if (suffix == ".png" || suffix == ".mp4" || suffix == ".ico")
    {
        fin.open(path, std::ios::binary);
    }
    if (!fin.is_open())
    {
        // 如果打开失败
        return readfile("./website/404.html", ".html", body);
    }
    // 获取文件大小
    fin.seekg(0, std::ios::end); // 将文件指针定位到文件结尾
    // 文件大小类型是 : std::streampos
    std::streampos filesize = fin.tellg();
    // tellg(); 返回文件指针相对于文件开始距离,也就是文件大小
    fin.seekg(0, std::ios::beg); // 再把文件指针定位回去

    // std::ios::beg：相对于文件开头。
    // std::ios::cur：相对于当前读取位置。
    // std::ios::end：相对于文件末尾。

    body.resize(filesize);

    fin.read(const_cast<char *>(body.c_str()), filesize);

    // getline通常用来读取文本文件
    //  std::string line;
    //  while (std::getline(fin, line))
    //  {
    //      body += line;
    //  }

    fin.close();
    return true;
}
std::string con_type(std::string str)
{
    if (str == ".html")
    {
        return "text/html";
    }
    else if (str == ".png")
    {
        return "image/png";
    }
    else if (str == ".mp4")
    {
        return "video/mp4";
    }
    else if (str == ".ico")
    {
        return "image/x-icon";
    }
    return "text/html";
}

// 文件的大小
bool readFile(const std::string resource, char *buffer, int size)
{
    std::ifstream in(resource, std::ios::binary);
    if (!in.is_open())
        return false; // resource not found

    in.read(buffer, size);
    // std::string line;
    // while(std::getline(in, line))
    // {
    //     *out += line;
    // }

    in.close();
    return true;
}

bool func(zxf::request &req, zxf::response &resp)
{

    // std::cout << "  ---------------------------------- http_request start----------------------------" << std::endl;
    // std::cout << "  ---------------------------------- http_request start----------------------------" << std::endl;
    // std::cout << "  ---------------------------------- http_request start----------------------------" << std::endl;
    // std::cout << req._buffer << std::endl;
    // std::cout << "  ---------------------------------- http_request end------------------------------" << std::endl;

    // std::string respline = "http/1.1 200 OK\r\n";
    std::string respline = "HTTP/1.1 200 OK\r\n";
    std::string respheader1 = "Content-Type:";
    respheader1 += con_type(req._suffix);
    respheader1 += "\r\n";
    std::string respheader2 = "Content-Length:";
    std::string respblank = "\r\n";
    // std::string body = "<!DOCTYPE html>< head ><meta charset =\"UTF-8\">< title>index.hyml</ title></ head><body><h1> 这是一个测试网页</ h1></ body> < / html >";
    // std::string body = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>index.hyml</title></head><body><h1>这是一个测试网页</h1></body></html> ";
    std::string body = "";
    // 此处写的是以文本的新式读取一个图片
    // 但是我们知道图片是一个二进制文件,所以读取读取成功之后,再浏览器显示的时候会出问题
    // 所以我们要判断文件的后缀,填写适当的Content-Type: 和  读取方式


    readfile(req._path, req._suffix, body);
    std::cout <<"body.size()"<< body.size() << std::endl;
    std::cout <<"req._size"<< req._size << std::endl;
    

    // 文件读取到string之后他的文件大小可能会改变,
    // 所以这里body.size(),不一定就对,所以需要我们去读取文件的大小
    // respheader2 += std::to_string(body.size());
    // 需要文件级别的大小
    respheader2 += std::to_string(req._size);
    respheader2 += "\r\n";

    // std::string body;
    //  body.resize(req.size + 1);
    //  if (!Util::readFile(req.path, (char *)body.c_str(), req.size))
    //  {
    //      Util::readFile(html_404, (char *)body.c_str(), req.size); // 一定能成功
    //  }

    resp._buffer += respline;
    resp._buffer += respheader1;
    resp._buffer += respheader2;
    resp._buffer += respblank;
    std::cout << "  ---------------------------------- http_response start----------------------------" << std::endl;
    std::cout << "  ---------------------------------- http_response start----------------------------" << std::endl;
    std::cout << "  ---------------------------------- http_response start----------------------------" << std::endl;
    std::cout << "  ---------------------------------- http_response start----------------------------" << std::endl;
    std::cout << resp._buffer << std::endl;
    std::cout << "  ---------------------------------- http_response end------------------------------" << std::endl;
    resp._buffer += body;

    return true;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        user();
        return 1;
    }

    int16_t port = std::stoi(argv[1]);
    // int16_t port = std::stoi(std::string(argv[1]));
    std::unique_ptr<zxf::Http_server> httpsvr(new zxf::Http_server(port));
    httpsvr->initServer();
    httpsvr->start(func);

    // zxf::Tcp_server ss(port);
    // // //守护进程化
    // // daemonSelf();
    // // 就和当前会话无关了
    // ss.initServer();
    // ss.start();

    return 0;
}

// int main() {
//     // 二进制文件路径
//     std::string filePath = "example.bin";

//     // 创建输入文件流对象
//     std::ifstream file(filePath, std::ios::binary);

//     if (file) {
//         // 获取文件大小
//         file.seekg(0, std::ios::end);
//         std::streampos fileSize = file.tellg();
//         file.seekg(0, std::ios::beg);

//         // 创建缓冲区来存储文件内容
//         char* buffer = new char[fileSize];

//         // 读取文件内容到缓冲区
//         file.read(buffer, fileSize);

//         // 关闭文件流
//         file.close();

//         // 打印读取到的数据（以十六进制形式）
//         for (std::streamsize i = 0; i < fileSize; ++i) {
//             std::cout << std::hex << (unsigned int)(unsigned char)buffer[i] << ' ';
//         }

//         // 释放缓冲区内存
//         delete[] buffer;
//     } else {
//         // 文件打开失败
//         std::cout << "Failed to open the file: " << filePath << std::endl;
//     }
// }